package it.okkam.giovo;

import it.okkam.costants.Costanti;
import it.okkam.importdatacreaterdf.DatiCatasto;
import it.okkam.strutturedati.AttributiParticella;
import it.okkam.strutturedati.Particella;
import it.okkam.strutturedati.ParticellaCatastale;
import it.okkam.strutturedati.Poligono;
import it.okkam.strutturedati.Punto;
import it.okkam.strutturedati.Vertice;
import it.okkam.utility.ApriStream;
import it.okkam.utility.CoordinateConversion;
import it.okkam.utility.S;
import it.okkam.utility.SGeo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.RDF;

public class DatiCatastoGiovo implements DatiCatasto {
	public static void main(String[] args) {
		DatiCatastoGiovo datiCatasto = new DatiCatastoGiovo();
		List<ParticellaCatastale> lista = datiCatasto.leggiParticelle("/home/okkam/Nicola/Dati catastali completi/giovo_coord.txt",
				"/home/okkam/Nicola/Dati catastali completi/giovo_attr.txt",
				"Giovo");
		datiCatasto.creaFileRDF("ciao", lista, "TURTLE");
	}

	public List<ParticellaCatastale> leggiParticelle(String filePoligoniPath,
			String fileParticellePath, String comune) {

		ArrayList<ParticellaCatastale> listaParticelleCatastali = new ArrayList<ParticellaCatastale>();
		ArrayList<String> contenutoFilePoligoni = null;
		
		ArrayList<String> contenutoFileAttributi = null;
		ArrayList<Particella> listaParticelleLette = new ArrayList<Particella>();
		ArrayList<AttributiParticella> listaAttributiLetti = new ArrayList<AttributiParticella>();
		ApriStream apriStream = new ApriStream();
		contenutoFilePoligoni = apriStream.apriStream(filePoligoniPath); // lettura
																			// file
																			// Poligoni
		contenutoFileAttributi = apriStream.apriStream(fileParticellePath); // lettura
																			// file
																			// Attributi

		listaParticelleLette = leggiParticelle(contenutoFilePoligoni);
		listaAttributiLetti = leggiAttributi(contenutoFileAttributi);
		listaParticelleCatastali = creaListaParticelleCatastali(listaParticelleLette, listaAttributiLetti, comune);
		return listaParticelleCatastali;

	}

	@Override
	public File creaFileRDF(String nomeFile,List<ParticellaCatastale> listaParticelleCatastali,String serializzazione) {
		File fileGiovordf = new File("/home/okkam/Nicola/Dati catastali completi/catastoGiovo.rdf");
		Model model = ModelFactory.createDefaultModel();
		String ontologiaGiovoCatasto = "http://www.okkam.it/ont/particella_catastale.owl#/giovo/castasto";
		model.setNsPrefix("pc", "http://www.okkam.it/ont/particella_catastale.owl#"); // set del prefisso
		for(ParticellaCatastale particella:listaParticelleCatastali){
			String particellaURI = null;
			String poligonoURI = null;
			String puntoURI = null;
			String verticeURI = null;
			
			
			String numeroEDenominatore = getNumEDen(particella);
			particellaURI = creaURIParticella(ontologiaGiovoCatasto, numeroEDenominatore, particella);
			
			// questo blocco  e' da aggiungere a un metodo privato
			
			Resource particellaRisorsa = model.createResource(particellaURI);
			particellaRisorsa.addProperty(S.haComuneCatastale, particella.getComune());
			particellaRisorsa.addProperty(S.haCodiceComuneCatastale, particella.getCodiceComune());
			particellaRisorsa.addProperty(S.haNumero, particella.getNumero());
			if (particella.getDenominatore()!=null){
				particellaRisorsa.addProperty(S.haDenominatore, particella.getDenominatore());}
			if (particella.getEdificialeFondiaria().equalsIgnoreCase("edificiale")){
				//text here caso EDIFICIALE
				particellaRisorsa.addProperty(S.eDiTipo, "edificiale");
			}
			else{
				//text here caso Fondiaria
				particellaRisorsa.addProperty(S.eDiTipo, "fondiaria");
			}
			//System.out.println(particellaRisorsa);
			//Model model = creaRisorsaParticella(particella,  particellaURI);
			Poligono poligonoLetto = particella.getPoligono();
			
			
			//particellaRisorsa.addProperty(S.haCentro, puntoURI);
			
			poligonoURI = creaURIPoligono(ontologiaGiovoCatasto, particella);
			Resource poligonoRisorsa = model.createResource(poligonoURI);
			particellaRisorsa.addProperty(S.haPoligono, poligonoRisorsa);
			Set<Vertice> listaVertici = poligonoLetto.getPoligono();
			
			for (Vertice verticeLetto: listaVertici){
				int ordine = verticeLetto.getCardinalita();
				if (ordine == 1){
						puntoURI = creaURIPunto(ontologiaGiovoCatasto, particella.getCentro());
						Resource centroRisorsa = model.createResource(puntoURI);
						centroRisorsa.addProperty(SGeo.lat, Double.toString(particella.getCentro().getX()));
						centroRisorsa.addProperty(SGeo.long_, Double.toString(particella.getCentro().getY()));
						//centroRisorsa.addLiteral(S.haLatitudineWGS84Decimale, Double.toString(particella.getCentro().getX()));
						//centroRisorsa.addLiteral(S.haLongitudineWGS84Decimale, Double.toString(particella.getCentro().getY()));
						poligonoRisorsa.addProperty(S.haCentro, centroRisorsa);}				
				
				Punto puntoLetto = verticeLetto.getVertice();
				puntoURI = creaURIPunto(ontologiaGiovoCatasto, puntoLetto);
				verticeURI = creaURIVertice(poligonoURI, puntoURI, ontologiaGiovoCatasto, Integer.toString(ordine));
				Resource verticeRisorsa = model.createResource(verticeURI);	
				Resource puntoRisorsa = model.createResource(puntoURI);
				puntoRisorsa.addProperty(SGeo.lat, Double.toString(puntoLetto.getX()));
				puntoRisorsa.addProperty(SGeo.long_, Double.toString(puntoLetto.getY()));
				//puntoRisorsa.addLiteral(S.haLatitudineWGS84Decimale, Double.toString(puntoLetto.getX()));
				//puntoRisorsa.addLiteral(S.haLongitudineWGS84Decimale, Double.toString(puntoLetto.getY()));
				verticeRisorsa.addProperty(S.haPunto, puntoRisorsa);
				verticeRisorsa.addProperty(S.haNumeroOrdine, Integer.toString(ordine));
				//verticeRisorsa.addLiteral(S.haNumeroOrdine, Integer.toString(ordine));
				poligonoRisorsa.addProperty(S.haVertice, verticeURI);					
			}
			
		}
		
		try{
		model.write(new PrintWriter(fileGiovordf), serializzazione);
		}
		catch(FileNotFoundException e) {			
			e.printStackTrace();
		}
		System.out.println("Creazione file " + fileGiovordf.getName() +" terminata!");
		return fileGiovordf;
	}

	// METODI PUBBLICI

	public double convertiTestoToNumero(String coordinataTestuale) {
		double coordinata = 0;
		int potenza;
		String radice, segno, potenzaStringa;
		if (coordinataTestuale != null) {
			// estraggo la radice della coordinata
			int indice = coordinataTestuale.indexOf('E');
			radice = coordinataTestuale.substring(0, indice);
			coordinata = Double.parseDouble(radice);
			// estraggo il segno della potenza
			segno = coordinataTestuale.substring((indice + 1), (indice + 2));
			// estraggo l'esponente
			potenzaStringa = coordinataTestuale.substring(indice + 2);
			potenza = Integer.parseInt(potenzaStringa);

			// adegue l'esponente al segno
			if (segno.equals("-"))
				potenza = potenza * (-1);
			// calcolo la coordinata
			coordinata = coordinata * (Math.pow(10, potenza));

			return coordinata;
		} else
			return 0.0;
	}

	// METODI PRIVATI

	private Vertice leggiVertice(String lettura, int indice) {
		Vertice vertex = new Vertice();
		Punto puntoLetto = new Punto();

		StringTokenizer st = new StringTokenizer(lettura, " ");
		while (st.hasMoreTokens()) {
			String coordX = st.nextToken();
			String coordY = st.nextToken();
			double cX = convertiTestoToNumero(coordX);
			double cY = convertiTestoToNumero(coordY);
			double lat = utm2Lat(cX, cY, "32 T "/* NORD_ITALIA */);
			double lon = utm2Lon(cX, cY, "32 T "/* NORD_ITALIA */);
			puntoLetto.setX(lat);
			puntoLetto.setY(lon);
			// System.out.println(lat + " " + lon);
			vertex.setVertice(puntoLetto);
			vertex.setCardinalita(indice);
		}

		return vertex;
	}

	private Punto leggiCentro(String lettura) {

		Punto puntoLetto = null;

		StringTokenizer st = new StringTokenizer(lettura, " ");
		int numTokens = st.countTokens();
		if (numTokens == 3) {
			while (st.hasMoreTokens()) {

				// leggi centro
				String numeroProgressivo = st.nextToken(); // salto una riga per
															// saltare il
															// progressivo
				String coordX = st.nextToken();
				String coordY = st.nextToken();
				double cX = convertiTestoToNumero(coordX);
				double cY = convertiTestoToNumero(coordY);
				double lat = utm2Lat(cX, cY, "32 T "/* NORD_ITALIA */);
				double lon = utm2Lon(cX, cY, "32 T "/* NORD_ITALIA */);
				puntoLetto = new Punto();
				puntoLetto.setX(lat);
				puntoLetto.setY(lon);
			}
		} else {
			System.out.println("Errore in " + lettura);
		}
		return puntoLetto;

	}

	private String leggiProgressivo(String lettura) {
		StringTokenizer st = new StringTokenizer(lettura, " ");
		String progressivo = new String();

		progressivo = st.nextToken();

		return progressivo;
	}

	private double utm2Lat(Double utmLat, Double utmLon, String zona) {

		CoordinateConversion converter = new CoordinateConversion();

		String utmLatStr = Double.toString(utmLat);
		String utmLonStr = Double.toString(utmLon);
		String utmCoordinates = zona + utmLatStr + " " + utmLonStr;

		double[] latLon = converter.utm2LatLon(utmCoordinates);

		double lat = latLon[0];
		return lat;

	}

	private double utm2Lon(Double utmLat, Double utmLon, String zona) {

		CoordinateConversion converter = new CoordinateConversion();

		String utmLatStr = Double.toString(utmLat);
		String utmLonStr = Double.toString(utmLon);
		String utmCoordinates = zona + utmLatStr + " " + utmLonStr;

		double[] latLon = converter.utm2LatLon(utmCoordinates);
		double longitudine = latLon[1];

		return longitudine;
	}

	private ArrayList<ParticellaCatastale> creaListaParticelleCatastali(
			ArrayList<Particella> listaParticelleLette,
			ArrayList<AttributiParticella> listaAttributiLetti, String comune) {
		ArrayList<ParticellaCatastale> listaPC = new ArrayList<ParticellaCatastale>();
		for (int i = 0; i < listaAttributiLetti.size(); i++) {
			Particella particellaIndagata = new Particella();
			AttributiParticella attributiParticellaIndagata = new AttributiParticella();
			particellaIndagata = listaParticelleLette.get(i);
			attributiParticellaIndagata = listaAttributiLetti.get(i);

			if (particellaIndagata.getProgressivo().equals(
					attributiParticellaIndagata.getProgressivo())) {
				ParticellaCatastale particellaCatastaleLetta = new ParticellaCatastale();
				if (attributiParticellaIndagata.getPrincipalePertinenza()
						.equals("principale")) {
					// set codice comune
					particellaCatastaleLetta
							.setCodiceComune(Costanti.CODICE_GIOVO);
					// set numero
					particellaCatastaleLetta
							.setNumero(attributiParticellaIndagata.getNumero());
					// set denominatore
					particellaCatastaleLetta
							.setDenominatore(attributiParticellaIndagata
									.getDenominatore());
					// set comune
					particellaCatastaleLetta.setComune(comune);
					// set poligono
					particellaCatastaleLetta.setPoligono(particellaIndagata
							.getPoligono());
					// set centro
					particellaCatastaleLetta.setCentro(particellaIndagata
							.getCentro());
					// set edificiale
					if (attributiParticellaIndagata.isPresenzaPunto()) {
						particellaCatastaleLetta
								.setEdificialeFondiaria("Edificiale");
					} else {
						particellaCatastaleLetta
								.setEdificialeFondiaria("Fondiaria");
					}
					//

					listaPC.add(particellaCatastaleLetta);

				}
			}
		}
		return listaPC;
	}

	private ArrayList<AttributiParticella> leggiAttributi(
			ArrayList<String> contenutoFileAttributi) {
		ArrayList<AttributiParticella> listaAttributi = new ArrayList<AttributiParticella>();
		for (String rigaLetta : contenutoFileAttributi) {
			//
			AttributiParticella attributiParticellaLetta = new AttributiParticella();
			String progressivo, principalePertinenza, numeroDenominatore;

			if (!(rigaLetta.startsWith("n"))) {
				String[] partiRigaLetta = rigaLetta.split(" "); // da migliorare
																// (controllo se
																// ci sono
																// errori)

				// set progressivo
				progressivo = partiRigaLetta[0];

				attributiParticellaLetta.setProgressivo(progressivo);

				// set pertinenza o principale
				principalePertinenza = partiRigaLetta[1];

				if (principalePertinenza.equals("C")) {
					attributiParticellaLetta
							.setPrincipalePertinenza("pertinenza");
				} else {
					attributiParticellaLetta
							.setPrincipalePertinenza("principale");
				}

				// set numero denominatore e punto
				numeroDenominatore = partiRigaLetta[2];

				// controllo se c'e' il punto
				if (numeroDenominatore.startsWith(".")) {
					attributiParticellaLetta.setPresenzaPunto(true);
					numeroDenominatore = numeroDenominatore.substring(1);
				} else {
					attributiParticellaLetta.setPresenzaPunto(false);
				}
				// controllo se c'e' la /
				if (numeroDenominatore.contains("/")) {
					String stringaDaDividere = numeroDenominatore;
					String delims = "/";
					String[] tokens = stringaDaDividere.split(delims);
					attributiParticellaLetta.setNumero(tokens[0]);
					attributiParticellaLetta.setDenominatore(tokens[1]);
				} else {
					attributiParticellaLetta.setNumero(numeroDenominatore);
				}
				// carico gli attributi letti sulla lista
				listaAttributi.add(attributiParticellaLetta);
			}

		}
		return listaAttributi;
	}

	private ArrayList<Particella> leggiParticelle(
			ArrayList<String> contenutoFilePoligoni) {
		ArrayList<Particella> listaParticelleLettura = new ArrayList<Particella>();
		boolean flagErrore = false;
		Poligono poligonoLetto = null;
		Set<Vertice> puntiPoligono = null;
		Punto centroParticella = new Punto();
		String progressivoParticella = new String();
		int indiceOrdine = 0;

		for (String rigaLetta : contenutoFilePoligoni) {

			// gestione errore
			if (rigaLetta.startsWith("-")) {
				// caso errore
				flagErrore = true;
			} else {
				if (rigaLetta.equals("END")) {

					{
						if (flagErrore == false) {
							// fine poligono
							poligonoLetto.setPoligono(puntiPoligono); // carico
																		// i
																		// punti
																		// del
																		// poligono

							// creo la particella e la popolo
							Particella particellaLetta = new Particella();
							particellaLetta.setPoligono(poligonoLetto);
							particellaLetta.setCentro(centroParticella);
							particellaLetta
									.setProgressivo(progressivoParticella);

							// carico la particella sulla lista delle particelle
							// lette
							listaParticelleLettura.add(particellaLetta);

							// mi preparo a leggere un'altra particella
							indiceOrdine = 0;
						} else {
							flagErrore = false;
						}
					}
				} else {
					if (flagErrore == false) {
						if (!rigaLetta.startsWith("0")) {
							// caso errore con -99999

							// caso centroide
							poligonoLetto = new Poligono();
							puntiPoligono = new HashSet<Vertice>();
							centroParticella = leggiCentro(rigaLetta);
							progressivoParticella = leggiProgressivo(rigaLetta);

						} else {
							// caso vertice
							Vertice vertice = new Vertice();
							indiceOrdine++;
							vertice = leggiVertice(rigaLetta, indiceOrdine);
							puntiPoligono.add(vertice);
						}
					}
				}
			}
		}

		return listaParticelleLettura;
	}
	
	private String creaURIPunto(String ontologia, Punto punto){
		String URIpunto = null; 
		ontologia = ontologia + "/punto";
		
		URIpunto = ontologia + "/lat/" + getParteIntera(punto.getX()) + "/" + getParteFrazionaria(punto.getX()) + "/lon/" + getParteIntera(punto.getY()) + "/" +getParteFrazionaria(punto.getY()) + "/wgs84"; 
		
		return URIpunto;
	}
	
	private String creaURIVertice (String URIpoligono , String URIpunto , String URIontologia , String ordine ){
		String URIvertice = URIpoligono;
		int indice = URIontologia.length();
		String subURI = URIpunto.substring(indice);
		URIvertice = URIvertice + subURI + "/w/" + ordine;		
		return URIvertice;
		
	}
	private String getParteIntera (double numero){
		String intera=null;
		String numeroStr = Double.toString(numero);
		int punto = trovaPosizionePunto(numeroStr);
		intera = numeroStr.substring(0,punto);
		return intera;
	}
	
	private String getParteFrazionaria (double numero){
		String fraz=null;
		String numeroStr = Double.toString(numero);
		int punto = trovaPosizionePunto(numeroStr);
		fraz = numeroStr.substring(punto+1);
		return fraz;
	}
	
	private int trovaPosizionePunto (String stringaIndagata){
		int i= 0;
		for (int j=0; j < stringaIndagata.length() ; j++  ){
			if (stringaIndagata.charAt(j)=='.'){
				i=j;
			}
		}
		return i;
		
	}
	
	private String creaURIPoligono(String ontologia, ParticellaCatastale particella){
		String URIpoligono = null; 
		String numEDen = getNumEDen(particella);
		ontologia = ontologia + "/poligono";
		
		if (particella.getEdificialeFondiaria().equalsIgnoreCase("edificiale")){
			//text here caso EDIFICIALE
			URIpoligono = ontologia + "/" + "pe" + "/" + numEDen ;
		}
		else{
			//text here caso Fondiaria
			URIpoligono = ontologia + "/" + "pf" + "/" + numEDen;
		}
		return URIpoligono;
	}
	
	private String getNumEDen (ParticellaCatastale particella){
		String numEDen = particella.getNumero();
		if (particella.getDenominatore()!= null){
			numEDen = numEDen + "/" + particella.getDenominatore();
		}
		
		return numEDen;
	}
	private String creaURIParticella(String ontologia,String numEDen , ParticellaCatastale particella){
		String URIParticella = null;
		if (particella.getEdificialeFondiaria().equalsIgnoreCase("edificiale")){
			//text here caso EDIFICIALE
			URIParticella = ontologia + "/" + "pe" + "/" + numEDen ;
		}
		else{
			//text here caso Fondiaria
			URIParticella = ontologia + "/" + "pf" + "/" + numEDen;
		}
		
		return URIParticella;
	}

}
